/*
* Copyright 2010 Pavel Kozhin 
*
* Licensed under the Apache License, Version 2.0 (the "License"); 
* you may not use this file except in compliance with the License. 
* You may obtain a copy of the License at 
* 
* http://www.apache.org/licenses/LICENSE-2.0
* 
* Unless required by applicable law or agreed to in writing, software 
* distributed  under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
* See the License for the specific language governing permissions and 
* limitations under the License.
*
* Author: Pavel Kozhin.
*/

package org.bookmarksframework.core
{
	import flash.events.EventPhase;
	import flash.events.IEventDispatcher;
	
	import mx.collections.IList;
	import mx.events.CollectionEvent;
	import mx.events.CollectionEventKind;
	
	import org.bookmarksframework.target.IFragmentTarget;
	
	internal class RelationsController
	{
		private var fragment:IFragment;
		
		private var target:IEventDispatcher;
		
		private var relations:Array;
		
		public function RelationsController(fragment:IFragment)
		{
			this.fragment = fragment;
			this.target = fragment.target as IEventDispatcher;
			relations = fragment.relations.toArray(); 
			fragment.relations.addEventListener(
				CollectionEvent.COLLECTION_CHANGE, dispatchersChangeHandler);
		}
		
		public function init():void
		{
			if (target)
				target.removeEventListener(GetParentEvent.GET_PARENT, parentHandler);
			
			target = fragment.target as IEventDispatcher;
			
			if (target)
				target.addEventListener(GetParentEvent.GET_PARENT, parentHandler);
			
			refreshDispatchers();
		}
		
		public function execute():IFragment
		{
			var evt:GetParentEvent = new GetParentEvent();
			fragment.host.dispatchEvent(evt);
			return evt.fragment;
		}
		
		public function destroy():void
		{
			if (target)
				target.removeEventListener(GetParentEvent.GET_PARENT, parentHandler);
			
			fragment.relations.removeAll();
			fragment.relations.removeEventListener(
				CollectionEvent.COLLECTION_CHANGE, dispatchersChangeHandler);
		}
		
		private function dispatchersChangeHandler(event:CollectionEvent):void
		{
			if (event.kind == CollectionEventKind.ADD || 
				event.kind == CollectionEventKind.REMOVE ||
				event.kind == CollectionEventKind.RESET)
			{
				refreshDispatchers();
			}
		}
		
		private function parentHandler(event:GetParentEvent):void
		{
			if ((relations.indexOf(event.target) != -1) || 
				event.eventPhase == EventPhase.BUBBLING_PHASE)
			{
				event.stopImmediatePropagation();
				event.fragment = fragment;
			}
		}
		
		private function refreshDispatchers():void
		{
			var len:int = relations.length;
			var dispatcher:IEventDispatcher;
			var i:int;
			
			for (i = 0; i < len; ++i)
			{
				dispatcher = relations[i] as IEventDispatcher;
				if (dispatcher && dispatcher != target)
					dispatcher.removeEventListener(GetParentEvent.GET_PARENT, parentHandler);
			}
			relations = fragment.relations.toArray();
			len = relations.length;
			
			for (i = 0; i < len; ++i)
			{
				dispatcher = relations[i] as IEventDispatcher;
				if (dispatcher && dispatcher != target)
					dispatcher.addEventListener(GetParentEvent.GET_PARENT, parentHandler);
			}
		}
	}
}

import flash.events.Event;

import org.bookmarksframework.core.IFragment;

final class GetParentEvent extends Event {
	
	internal static const GET_PARENT:String = "org.bookmarksframework.core.GetParentEvent.GET_PARENT";
	
	internal var fragment:IFragment = null;
	
	public function GetParentEvent()
	{
		super(GET_PARENT, true);
	}
}